/*
 * commandParser.cpp
 *
 *  Created on: 11.02.2012
 *      Author: ignacio
 */


#include "commandParser.h"
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;


#include <boost/program_options.hpp>
#include <boost/any.hpp>

namespace neurignacio{

commandOptions::commandOptions(int argc, char* argv[])
{
	const string HELP_OPTION = "help";
	const string HELP_OPTION_SHORT = "h";
	const string HELP_OPTION_DESCRIPTION="Print this help screen and exit";
	// OPTIONS
	const string NUMOFFRAMES_OPTION = "frames";
	const string VERBOSITY_OPTION = "verbosity";
	const string WINDOWSIZE_X_OPTION = "window-size-x";
	const string WINDOWSIZE_Y_OPTION = "window-size-y";
	const string WORLDSIZE_X_OPTION = "world-size-x";
	const string WORLDSIZE_Y_OPTION = "world-size-y";

	const string CHARACTERPOSITION_X_OPTION = "character-position-x";
	const string CHARACTERPOSITION_Y_OPTION = "character-position-y";
	const string CHARACTERPOSITION_Z_OPTION = "character-position-z";
	const string CHARACTERORIENTATION_OPTION = "character-orientation";
	const string CHARACTERMINVELOCITY_OPTION = "character-min-velocity";
	const string CHARACTERMAXSPEED_OPTION = "character-max-speed";
	const string CHARACTERMAXROTATION_OPTION = "character-max-rotation";
	const string CHARACTERMAXACCELERATION_OPTION = "character-max-acceleration";
	const string CHARACTERMAXANGULARACCELERATION_OPTION = "character-max-angular-acceleration";
	const string CHARACTERVOLATILITY_OPTION = "character-volatility";
	const string CHARACTERTURNSPEED_OPTION = "character-turn-speed";

	const string TARGETPOSITION_X_OPTION = "target-position-x";
	const string TARGETPOSITION_Y_OPTION = "target-position-y";
	const string TARGETPOSITION_Z_OPTION = "target-position-z";
	const string TARGETORIENTATION_OPTION = "target-orientation";
	const string TARGETMINVELOCITY_OPTION = "target-min-velocity";
	const string TARGETMAXSPEED_OPTION = "target-max-speed";
	const string TARGETMAXROTATION_OPTION = "target-max-rotation";
	const string TARGETMAXACCELERATION_OPTION = "target-max-acceleration";
	const string TARGETMAXANGULARACCELERATION_OPTION = "target-max-angular-acceleration";
	const string TARGETVOLATILITY_OPTION = "target-volatility";
	const string TARGETTURNSPEED_OPTION = "target-turn-speed";

	const string TIMETOTARGETLINEAR_OPTION = "time-to-target-linear";
	const string TARGETRADIUSLINEAR_OPTION = "target-radius-linear";
	const string SLOWRADIUSLINEAR_OPTION = "slow-radius-linear";
	const string TIMETOTARGETANGULAR_OPTION = "time-to-target-angular";
	const string TARGETRADIUSANGULAR_OPTION = "target-radius-angular";
	const string SLOWRADIUSANGULAR_OPTION = "slow-radius-angular";
	const string MAXPREDICTION_OPTION = "max-prediction";
	// HELP STRING
	const string NUMOFFRAMES_DESCRIPTION = "Number of Frames";
	const string VERBOSITY_DESCRIPTION = "Verbosity (Display Debug Messages)";
	const string WINDOWSIZE_X_DESCRIPTION = "Width of the Display Window (0..+x)";
	const string WINDOWSIZE_Y_DESCRIPTION = "Height of the Display Window (0..+y)";
	const string WORLDSIZE_X_DESCRIPTION = "Width of the World (-x..0..x)";
	const string WORLDSIZE_Y_DESCRIPTION = "Heigth of the World (-y..0..y)";

	const string CHARACTERPOSITION_X_DESCRIPTION = "Initial Position of the Character in the World (X)";
	const string CHARACTERPOSITION_Y_DESCRIPTION = "Initial Position of the Character in the World (Y)";
	const string CHARACTERPOSITION_Z_DESCRIPTION = "Initial Position of the Character in the World (Z)";
	const string CHARACTERORIENTATION_DESCRIPTION = "Initial Orientation of the Character";
	const string CHARACTERMINVELOCITY_DESCRIPTION = "Velocity of the Character to be considered as Zero";
	const string CHARACTERMAXSPEED_DESCRIPTION = "Maximum Linear Velocity of the Character";
	const string CHARACTERMAXROTATION_DESCRIPTION = "Maximum Angular Velocity (Rotation) of the Character";
	const string CHARACTERMAXACCELERATION_DESCRIPTION = "Maximum Linear Acceleration of the Character";
	const string CHARACTERMAXANGULARACCELERATION_DESCRIPTION = "Maximum Angular Acceleration of the Character";
	const string CHARACTERVOLATILITY_DESCRIPTION = "Chance for changing direction of the Character when wandering";
	const string CHARACTERTURNSPEED_DESCRIPTION = "Speed for Turning of the Character ????";

	const string TARGETPOSITION_X_DESCRIPTION = "Initial Position of the target in the World (X)";
	const string TARGETPOSITION_Y_DESCRIPTION = "Initial Position of the target in the World (Y)";
	const string TARGETPOSITION_Z_DESCRIPTION = "Initial Position of the target in the World (Z)";
	const string TARGETORIENTATION_DESCRIPTION = "Initial Orientation of the target";
	const string TARGETMINVELOCITY_DESCRIPTION = "Velocity of the target to be considered as Zero";
	const string TARGETMAXSPEED_DESCRIPTION = "Maximum Linear Velocity of the target";
	const string TARGETMAXROTATION_DESCRIPTION = "Maximum Angular Velocity (Rotation) of the target";
	const string TARGETMAXACCELERATION_DESCRIPTION = "Maximum Linear Acceleration of the target";
	const string TARGETMAXANGULARACCELERATION_DESCRIPTION = "Maximum Angular Acceleration of the target";
	const string TARGETVOLATILITY_DESCRIPTION = "Chance for changing direction of the target when wandering";
	const string TARGETTURNSPEED_DESCRIPTION = "Speed for Turning of the target ????";

	const string TIMETOTARGETLINEAR_DESCRIPTION = "Time in which the Character wants to arrive to the target by linear steering";
	const string TARGETRADIUSLINEAR_DESCRIPTION = "Linear Distance to the Target that the Character will consider as Zero";
	const string SLOWRADIUSLINEAR_DESCRIPTION = "Linear Distance to the Target at which the Character will decelerate";
	const string TIMETOTARGETANGULAR_DESCRIPTION = "Time in which the Character wants to arrive to the target by angular steering";
	const string TARGETRADIUSANGULAR_DESCRIPTION = "Angular Distance to the Target that the Character will consider as Zero";
	const string SLOWRADIUSANGULAR_DESCRIPTION = "Angular Distance to the Target at which the Character will decelerate";
	const string MAXPREDICTION_DESCRIPTION = "Maximum Time forehead that the Character will use to predict the trajectory of the Target";

	// Check if there are any options
	if (argc<=1)
		{
			string errorString="Missing command options\n";
			errorString += "Please refer to the help for use instructions ( ";
			errorString += argv[0];
			errorString += " --help or ";
			errorString += argv[0];
			errorString += "-h )";
			cerr << errorString << endl;//error(neurignacio::NO_ARGUMENTS,errorString);
		}


	const string USAGE_DESCRIPTION = "\nUsage: "+string(argv[0])+" [options] input-file\n";
	const string EXAMPLES = "Examples:\n  "+string(argv[0])+" \n";
	const string OPTIONS_HEADER = "Options Supported:";

	try
	{
		boost::program_options::options_description desc(string(USAGE_DESCRIPTION+EXAMPLES+"\n"+OPTIONS_HEADER).c_str());
		desc.add_options()
		(string(HELP_OPTION+","+HELP_OPTION_SHORT).c_str(), HELP_OPTION_DESCRIPTION.c_str())
		(string(NUMOFFRAMES_DESCRIPTION).c_str(), boost::program_options::value< unsigned long int >(),NUMOFFRAMES_OPTION.c_str())
		(string(VERBOSITY_DESCRIPTION).c_str(), VERBOSITY_OPTION.c_str())
		(string(WINDOWSIZE_X_DESCRIPTION).c_str(), boost::program_options::value< unsigned int >(),WINDOWSIZE_X_OPTION.c_str())
		(string(WINDOWSIZE_Y_DESCRIPTION).c_str(), boost::program_options::value< unsigned int >(),WINDOWSIZE_Y_OPTION.c_str())
		(string(WORLDSIZE_X_DESCRIPTION).c_str(), boost::program_options::value< float >(),WORLDSIZE_X_OPTION.c_str())
		(string(WORLDSIZE_Y_DESCRIPTION).c_str(), boost::program_options::value< float >(),WORLDSIZE_Y_OPTION.c_str())

		(string(CHARACTERPOSITION_X_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERPOSITION_X_OPTION.c_str())
		(string(CHARACTERPOSITION_Y_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERPOSITION_Y_OPTION.c_str())
		(string(CHARACTERPOSITION_Z_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERPOSITION_Z_OPTION.c_str())
		(string(CHARACTERORIENTATION_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERORIENTATION_OPTION.c_str())
		(string(CHARACTERMINVELOCITY_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERMINVELOCITY_OPTION.c_str())
		(string(CHARACTERMAXSPEED_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERMAXSPEED_OPTION.c_str())
		(string(CHARACTERMAXROTATION_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERMAXROTATION_OPTION.c_str())
		(string(CHARACTERMAXACCELERATION_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERMAXACCELERATION_OPTION.c_str())
		(string(CHARACTERMAXANGULARACCELERATION_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERMAXANGULARACCELERATION_OPTION.c_str())
		(string(CHARACTERVOLATILITY_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERVOLATILITY_OPTION.c_str())
		(string(CHARACTERTURNSPEED_DESCRIPTION).c_str(), boost::program_options::value< float >(),CHARACTERTURNSPEED_OPTION.c_str())

		(string(TARGETPOSITION_X_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETPOSITION_X_OPTION.c_str())
		(string(TARGETPOSITION_Y_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETPOSITION_Y_OPTION.c_str())
		(string(TARGETPOSITION_Z_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETPOSITION_Z_OPTION.c_str())
		(string(TARGETORIENTATION_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETORIENTATION_OPTION.c_str())
		(string(TARGETMINVELOCITY_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETMINVELOCITY_OPTION.c_str())
		(string(TARGETMAXSPEED_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETMAXSPEED_OPTION.c_str())
		(string(TARGETMAXROTATION_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETMAXROTATION_OPTION.c_str())
		(string(TARGETMAXACCELERATION_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETMAXACCELERATION_OPTION.c_str())
		(string(TARGETMAXANGULARACCELERATION_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETMAXANGULARACCELERATION_OPTION.c_str())
		(string(TARGETVOLATILITY_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETVOLATILITY_OPTION.c_str())
		(string(TARGETTURNSPEED_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETTURNSPEED_OPTION.c_str())

		(string(TIMETOTARGETLINEAR_DESCRIPTION).c_str(), boost::program_options::value< float >(),TIMETOTARGETLINEAR_OPTION.c_str())
		(string(TARGETRADIUSLINEAR_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETRADIUSLINEAR_OPTION.c_str())
		(string(SLOWRADIUSLINEAR_DESCRIPTION).c_str(), boost::program_options::value< float >(),SLOWRADIUSLINEAR_OPTION.c_str())
		(string(TIMETOTARGETANGULAR_DESCRIPTION).c_str(), boost::program_options::value< float >(),TIMETOTARGETANGULAR_OPTION.c_str())
		(string(TARGETRADIUSANGULAR_DESCRIPTION).c_str(), boost::program_options::value< float >(),TARGETRADIUSANGULAR_OPTION.c_str())
		(string(SLOWRADIUSANGULAR_DESCRIPTION).c_str(), boost::program_options::value< float >(),SLOWRADIUSANGULAR_OPTION.c_str())
		(string(MAXPREDICTION_DESCRIPTION).c_str(), boost::program_options::value< float >(),MAXPREDICTION_OPTION.c_str())
		;
		boost::program_options::positional_options_description p;
		p.add(NUMOFFRAMES_OPTION.c_str(), -1);

		boost::program_options::variables_map vm;
		boost::program_options::store(boost::program_options::command_line_parser(argc,argv).options(desc).positional(p).run(), vm);
		boost::program_options::notify(vm);

		if (vm.count(HELP_OPTION))
		{
			help = true;
			cout << desc << "\n";
		}
		if (vm.count(NUMOFFRAMES_OPTION)) numOfFrames= vm[NUMOFFRAMES_OPTION].as<float>();
		if (vm.count(VERBOSITY_OPTION)) verbosity= vm[VERBOSITY_OPTION].as<float>();
		if (vm.count(WINDOWSIZE_X_OPTION)) windowSize_X= vm[WINDOWSIZE_X_OPTION].as<float>();
		if (vm.count(WINDOWSIZE_Y_OPTION)) windowSize_Y= vm[WINDOWSIZE_Y_OPTION].as<float>();
		if (vm.count(WORLDSIZE_X_OPTION)) worldSize_X= vm[WORLDSIZE_X_OPTION].as<float>();
		if (vm.count(WORLDSIZE_Y_OPTION)) worldSize_Y= vm[WORLDSIZE_Y_OPTION].as<float>();

		if (vm.count(CHARACTERPOSITION_X_OPTION)) characterPosition_X= vm[CHARACTERPOSITION_X_OPTION].as<float>();
		if (vm.count(CHARACTERPOSITION_Y_OPTION)) characterPosition_Y= vm[CHARACTERPOSITION_Y_OPTION].as<float>();
		if (vm.count(CHARACTERPOSITION_Z_OPTION)) characterPosition_Z= vm[CHARACTERPOSITION_Z_OPTION].as<float>();
		if (vm.count(CHARACTERORIENTATION_OPTION)) characterOrientation= vm[CHARACTERORIENTATION_OPTION].as<float>();
		if (vm.count(CHARACTERMINVELOCITY_OPTION)) characterMinVelocity= vm[CHARACTERMINVELOCITY_OPTION].as<float>();
		if (vm.count(CHARACTERMAXSPEED_OPTION)) characterMaxSpeed= vm[CHARACTERMAXSPEED_OPTION].as<float>();
		if (vm.count(CHARACTERMAXROTATION_OPTION)) characterMaxRotation= vm[CHARACTERMAXROTATION_OPTION].as<float>();
		if (vm.count(CHARACTERMAXACCELERATION_OPTION)) characterMaxAcceleration= vm[CHARACTERMAXACCELERATION_OPTION].as<float>();
		if (vm.count(CHARACTERMAXANGULARACCELERATION_OPTION)) characterMaxAngularAcceleration= vm[CHARACTERMAXANGULARACCELERATION_OPTION].as<float>();
		if (vm.count(CHARACTERVOLATILITY_OPTION)) characterVolatility= vm[CHARACTERVOLATILITY_OPTION].as<float>();
		if (vm.count(CHARACTERTURNSPEED_OPTION)) characterTurnSpeed= vm[CHARACTERTURNSPEED_OPTION].as<float>();

		if (vm.count(TARGETPOSITION_X_OPTION)) targetPosition_X= vm[TARGETPOSITION_X_OPTION].as<float>();
		if (vm.count(TARGETPOSITION_Y_OPTION)) targetPosition_Y= vm[TARGETPOSITION_Y_OPTION].as<float>();
		if (vm.count(TARGETPOSITION_Z_OPTION)) targetPosition_Z= vm[TARGETPOSITION_Z_OPTION].as<float>();
		if (vm.count(TARGETORIENTATION_OPTION)) targetOrientation= vm[TARGETORIENTATION_OPTION].as<float>();
		if (vm.count(TARGETMINVELOCITY_OPTION)) targetMinVelocity= vm[TARGETMINVELOCITY_OPTION].as<float>();
		if (vm.count(TARGETMAXSPEED_OPTION)) targetMaxSpeed= vm[TARGETMAXSPEED_OPTION].as<float>();
		if (vm.count(TARGETMAXROTATION_OPTION)) targetMaxRotation= vm[TARGETMAXROTATION_OPTION].as<float>();
		if (vm.count(TARGETMAXACCELERATION_OPTION)) targetMaxAcceleration= vm[TARGETMAXACCELERATION_OPTION].as<float>();
		if (vm.count(TARGETMAXANGULARACCELERATION_OPTION)) targetMaxAngularAcceleration= vm[TARGETMAXANGULARACCELERATION_OPTION].as<float>();
		if (vm.count(TARGETVOLATILITY_OPTION)) targetVolatility= vm[TARGETVOLATILITY_OPTION].as<float>();
		if (vm.count(TARGETTURNSPEED_OPTION)) targetTurnSpeed= vm[TARGETTURNSPEED_OPTION].as<float>();

		if (vm.count(TIMETOTARGETLINEAR_OPTION)) timeToTargetLinear= vm[TIMETOTARGETLINEAR_OPTION].as<float>();
		if (vm.count(TARGETRADIUSLINEAR_OPTION)) targetRadiusLinear= vm[TARGETRADIUSLINEAR_OPTION].as<float>();
		if (vm.count(SLOWRADIUSLINEAR_OPTION)) slowRadiusLinear= vm[SLOWRADIUSLINEAR_OPTION].as<float>();
		if (vm.count(TIMETOTARGETANGULAR_OPTION)) timeToTargetAngular= vm[TIMETOTARGETANGULAR_OPTION].as<float>();
		if (vm.count(TARGETRADIUSANGULAR_OPTION)) targetRadiusAngular= vm[TARGETRADIUSANGULAR_OPTION].as<float>();
		if (vm.count(SLOWRADIUSANGULAR_OPTION)) slowRadiusAngular= vm[SLOWRADIUSANGULAR_OPTION].as<float>();
		if (vm.count(MAXPREDICTION_OPTION)) maxPrediction= vm[MAXPREDICTION_OPTION].as<float>();
	}
	catch (boost::program_options::error option)
	{
		//error(neurignacio::COMMAND_PARSER_EXCEPTION, option.what());
	}
}

} // end namespace neurignacio
